<?php

namespace addons\yungift\controller;

use addons\yungift\library\Constant;
use addons\yungift\library\Logic;
use addons\yungift\library\Super;
use addons\yungift\model\CardCode;
use addons\yungift\model\CardMain;
use addons\yungift\model\Config;
use addons\yungift\model\GiftCode;
use addons\yungift\model\GiftMain;
use addons\yungift\model\GiftOrder;
use addons\yungift\model\GiftSpec;
use addons\yungift\model\Norepeat;
use addons\yungift\model\UserAuth;
use addons\yungift\model\SmsCode;
use app\common\model\User;
use app\common\controller\Api;
use fast\Random;
use think\Db;
use think\Exception;
use think\exception\PDOException;
use think\Validate;


/**
 * 礼卡接口
 */
class Card extends Api
{
    protected $noNeedRight = ['*'];
    protected $noNeedLogin = ['*'];

    protected $platform;
    protected $cardId;
    protected $cardData;
    protected $cardCodeId;
    protected $cardCodeData;

    /**
     * 初始化操作
     * @access protected
     */
    protected function _initialize()
    {
        parent::_initialize();

        // 跨域请求检测
        check_cors_request();

        $this->platform = input('get.platform');

        // 礼卡数据
        if ($cardId = input('get.card_id')) {
            $this->cardData = CardMain::where(['id' => $cardId])->show()->find();
            if (! $this->cardData) {
                $this->error(__('活动已停止或没有参与权限'), null, Constant::INVALID_CARD);
            }
            $this->cardId = $this->cardData->id;
        }

        // 礼卡密数据
        if ($cardKey = input('get.card_key')) {
            if (! $this->cardCodeData = CardCode::get(['key' => $cardKey])) {
                $this->error(__('卡密无效'), null, Constant::INVALID_CARD_CODE);
            }
            if ($this->cardCodeData->status == CardCode::STATUS_WAIT_CARD) {
                $this->error(__('卡密还未制卡'), null, Constant::INVALID_CARD_CODE);
            }
            if ($this->cardCodeData->status == CardCode::STATUS_HAS_INVALID) {
                $this->error(__('卡密已过期'), null, Constant::INVALID_CARD_CODE);
            }
            $this->cardCodeId = $this->cardCodeData->id;
            $this->cardData = $this->cardCodeData->cardData;
            $this->cardId = $this->cardData->id;
        }
        // 生成预览链接
        $this->cardData->preview_url = '';
        if ($this->cardData) {
            $domain = Config::getGroupAttribute(Config::GROUP_BASE, 'h5_domain');
            if ($domain) {
                $previewUrl = trim($domain, '/') . '/#/pages/card/preindex';
                $params = [];
                $params['f'] = time() + 86400 * 3000;
                $prevKey = \think\Env::get('misc.prevKey');
                $sign = md5($this->cardId . $params['f'] . $prevKey);
                $params['ck'] = base64_encode($sign);
                $params['cid'] = $this->cardId;
                $previewUrl .= '?' . http_build_query($params);
                $this->cardData->preview_url = $previewUrl;
            }
        }
    }

    // 获取入口信息
    public function getEnterInfo()
    {
        $wxCode = $this->request->post('wx_code');
        $authKey = $this->request->post('auth_key');
        if (input('get.card_id')) {
            $result = Super::arrayGetSet($this->cardData,
                ['login_top_img', 'login_note', 'only_number', 'tips', 'preview_url']);
        } else {
            $result = Super::arrayGetSet(Config::getGroupAttributes(Config::GROUP_CARD),
                ['login_top_img', 'login_note', 'only_number', 'tips']);
            $result['login_top_img'] = empty($result['login_top_img']) ? '' : cdnurl($result['login_top_img'], true);
        }
        $result['only_number'] = (int)$result['only_number'];
        $result['mp_login'] = (int)Config::getGroupAttribute(Config::GROUP_MP, 'mp_login', 0);

        $openid = $source = null;
        $wxCodeData = $this->checkWxCode($wxCode);
        if ($wxCodeData) {
            $source = UserAuth::SOURCE_MINI;
            $openid = $wxCodeData['openid'];
        } elseif ($authKey) {
            $openid = Logic::getUserAuthOpenid($authKey, UserAuth::SOURCE_MP);
            $source = UserAuth::SOURCE_MP;
        }
        if ($openid) {
            if ($userId = Logic::getUserAuthUid($openid, $source)) {
                $cardCode = CardCode::where(['user_id' => $userId])
                    ->where('status', 'in',
                        [CardCode::STATUS_WAIT_VALID, CardCode::STATUS_HAS_VALID, CardCode::STATUS_HAS_EXCHANGE])
                    ->order('login_time desc')->find();
                if ($cardCode) {
                    $cardCode->key = strtolower(Random::alnum(32));
                    $cardCode->save();
                    $result['card_key'] = $cardCode->key;
                }
            }
        }

        $this->success('操作成功', $result);
    }

    // 根据卡密登录
    public function loginByCard()
    {
        $number = $this->request->post('number');
        $password = $this->request->post('password');
        $wxCode = $this->request->post('wx_code');
        $authKey = $this->request->post('auth_key');
        if (! $cardInfo = CardCode::get(['number' => $number])) {
            $this->error(__('礼卡不存在'));
        }
        if ($cardInfo->valid_count++ >= 500) {
            $this->error(__('验证次数超过500次，无法登录'));
        }
        if (! $cardInfo->cardData->only_number) {
            if ($cardInfo->status == CardCode::STATUS_WAIT_CARD) {
                $this->error(__('卡密还未制卡'));
            }
            if ($cardInfo->status == CardCode::STATUS_HAS_INVALID) {
                $this->error(__('卡密已过期'));
            }
            if ($cardInfo->password != $password) {
                $cardInfo->save();
                $this->error(__('密码不对'));
            }
        }

        // 检查微信code
        $openid = $source = null;
        $wxCodeData = $this->checkWxCode($wxCode);
        if ($wxCodeData) {
            $source = UserAuth::SOURCE_MINI;
            $openid = $wxCodeData['openid'];
        } elseif ($authKey) {
            $openid = Logic::getUserAuthOpenid($authKey, UserAuth::SOURCE_MP);
            $source = UserAuth::SOURCE_MP;
        }
        if ($openid) {
            $cardInfo->user_id = Logic::getUserAuthUid($openid, $source);
            if (! $cardInfo->user_id) {
                // 注册会员
                $username = 'yungift_c' . str_pad($cardInfo->id, 8, '0', STR_PAD_LEFT);
                if ($user = User::get(['username' => $username])) {
                    $cardInfo->user_id = $user->id;
                } else {
                    $password = str_pad($cardInfo->id, 8, '0', STR_PAD_LEFT);
                    $result = $this->auth->register($username, $password);
                    if (! $result) {
                        $this->error($this->auth->getError());
                    }
                    $cardInfo->user_id = $this->auth->id;
                }
                Logic::bindUserAuth($cardInfo->user_id, $openid, $source);
            }
            $cardInfo->login_time = time();
        }

        $cardInfo->key = strtolower(Random::alnum(32));
        $cardInfo->valid_count++;
        if ($cardInfo->status == CardCode::STATUS_WAIT_VALID) {
            $cardInfo->status = CardCode::STATUS_HAS_VALID;
        }
        $cardInfo->save();

        $this->success('操作成功', compact('cardInfo'));
    }

    /** * 发送手机验证码 */
    public function sendPhoneCaptcha()
    {
        $data = $this->request->post();
        $rule = [
            'phone'  => 'require',
            'cid'    => 'require',
        ];
        $msg = [
            'phone.require' => '手机号不能为空',
            'cid.require' => '缺少礼卡ID',
        ];
        $validate   = Validate::make($rule,$msg);
        $result = $validate->check($data);
        if (!$result) {
            $this->error($validate->getError());
        }
        $phone = trim($data['phone']);

        // 检查微信code
        $wxCodeData = $this->checkWxCode($data['wx_code'] ?? null);
        // 只给有卡密的发送账号
        if (! $cardInfo = CardCode::get(['phone' => $phone, 'card_id' => $data['cid']])) {
            $this->error(__('礼卡不存在'));
        }
        if ($cardInfo->cardData->only_number != 2) {
            $this->error(__('兑换方式不正确'));
        }
        
        if ($cardInfo->status == CardCode::STATUS_WAIT_CARD) {
            $this->error(__('卡密还未制卡'));
        }
        if ($cardInfo->status == CardCode::STATUS_HAS_INVALID) {
            $this->error(__('卡密已过期'));
        }


        // 校验手机号发送验证码次数
        $recordList = SmsCode::where(['phone' => $phone])
            ->where('created_at', '>=', strtotime('today'))
            ->order(['created_at' => SORT_DESC])->select();
        if (count($recordList) > 0) {
            if ($recordList[0]->created_at > time() - 60) {
                $this->error(__('一分钟之内只能发送一次验证码'));
            }
        }
        if (count($recordList) >= 10) {
            $this->error(__('今日验证码发送次数已达上限'));
        }

        // 微信用户发送验证码次数限制
        if ($wxCodeData) {
            $userCount = SmsCode::where(['openid' => $wxCodeData['openid']])
                ->where('created_at', '>=', strtotime('today'))->count();
            if ($userCount >= 20) {
                $this->error(__('今日验证码发送次数已达上限'));
            }
        }

        // 保存验证码
        $code = random_int(100000, 999999);
        $smsCode = new SmsCode();
        $smsCode->openid = $wxCodeData['openid'] ?? null;
        $smsCode->phone = $phone;
        $smsCode->code = $code;
        $smsCode->status = SmsCode::STATE_ING;
        $smsCode->expired_at = time() + 60 * 10;
        $smsCode->save();

        if ($error = Logic::sendAlisms($phone, $code)) {
            $this->error(__('短信发送失败: ' . $error));
        }

        $this->success('操作成功', null);
    }

    /**
     * 登录方式 - 手机验证码
     */
    public function loginByPhoneCaptcha()
    {
        $data = $this->request->post();
        $rule = [
            'phone'  => 'require',
            'captcha'    => 'require',
            'cid'     => 'require',
        ];
        $msg = [
            'phone.require' => '手机号不能为空',
            'captcha.require' => '缺少礼卡ID',
            'cid.require' => '缺少礼卡ID',
        ];
        $validate   = Validate::make($rule,$msg);
        if (! $validate->check($data)) {
            $this->error($validate->getError());
        }
        $wxCode = $this->request->post('wx_code');
        $authKey = $this->request->post('auth_key');
        $phone = trim($data['phone']);
        $cid = trim($data['cid']);

        // 检查微信code
        $openid = $source = null;
        $wxCodeData = $this->checkWxCode($wxCode);
        if ($wxCodeData) {
            $source = UserAuth::SOURCE_MINI;
            $openid = $wxCodeData['openid'];
        } elseif ($authKey) {
            $openid = Logic::getUserAuthOpenid($authKey, UserAuth::SOURCE_MP);
            $source = UserAuth::SOURCE_MP;
        }

        if (! $cardInfo = CardCode::get(['phone' => $phone, 'card_id' => $data['cid']])) {
            $this->error(__('礼卡不存在'));
        }
        if ($cardInfo->cardData->only_number != 2) {
            $this->error(__('兑换方式不正确'));
        }
        
        if ($cardInfo->status == CardCode::STATUS_WAIT_CARD) {
            $this->error(__('卡密还未制卡'));
        }
        if ($cardInfo->status == CardCode::STATUS_HAS_INVALID) {
            $this->error(__('卡密已过期'));
        }

        // 校验验证码
        $smsCode = SmsCode::where([
            'phone' => $phone,
            'code'  => trim($data['captcha'])
        ])->order(['created_at' => SORT_DESC])->find();
        if (! $smsCode) {
            $this->error(__('验证码错误'));
        }
        if ($smsCode->expired_at < time() || $smsCode->status != SmsCode::STATE_ING) {
            $this->error(__('验证码失效'));
        }
        $smsCode->status = SmsCode::STATE_END;
        $smsCode->save();

        if ($openid) {
            $cardInfo->user_id = Logic::getUserAuthUid($openid, $source);
            if (! $cardInfo->user_id) {
                // 注册会员
                $username = 'yungift_c' . str_pad($cardInfo->id, 8, '0', STR_PAD_LEFT);
                if ($user = User::get(['username' => $username])) {
                    $cardInfo->user_id = $user->id;
                } else {
                    $password = str_pad($cardInfo->id, 8, '0', STR_PAD_LEFT);
                    $result = $this->auth->register($username, $password);
                    if (! $result) {
                        $this->error($this->auth->getError());
                    }
                    $cardInfo->user_id = $this->auth->id;
                }
                Logic::bindUserAuth($cardInfo->user_id, $openid, $source);
            }
            $cardInfo->login_time = time();
        }

        $cardInfo->key = strtolower(Random::alnum(32));
        $cardInfo->valid_count++;
        if ($cardInfo->status == CardCode::STATUS_WAIT_VALID) {
            $cardInfo->status = CardCode::STATUS_HAS_VALID;
        }
        $cardInfo->save();

        $this->success('操作成功', compact('cardInfo'));

    }

    /**
     * 检查登录code
     *
     * @param $wxCode
     */
    private function checkWxCode($wxCode)
    {
        if (Config::getGroupAttribute(Config::GROUP_BASE, 'only_wechat')) {
            if (! $wxCode) {
                $this->error(__('微信登录code不能为空'));
            }
        }
        if ($wxCode) {
            if (! $wxCodeData = Logic::getMiniCodeData($wxCode, false)) {
                $this->error(__('获取微信登录信息失败'));
            }

            return $wxCodeData;
        }

        return null;
    }

    // 退出登录
    public function logout()
    {
        if ($this->cardCodeData) {
            $this->cardCodeData->key = null;
            $this->cardCodeData->user_id = 0;
            $this->cardCodeData->save();
        }

        $this->success('操作成功');
    }

    // 获取整体数据
    public function getWrapData()
    {
        // 礼卡数据
        $cardData = Super::arrayGetSet($this->cardData, ['home_top_img', 'content', 'state']);

        // 礼卡密数据
        $cardCodeData = Super::arrayGetSet($this->cardCodeData, ['number', 'chance_use']);
        $chanceLeft = $this->cardData['chance_count'] - $cardCodeData['chance_use'];
        $cardCodeData['chance_left'] = $chanceLeft > 0 ? $chanceLeft : 0;

        // 已兑礼品
        $giftIds = [];
        if ($this->cardData->gift_limit) {
            $giftIds = GiftOrder::where(['type' => GiftOrder::TYPE_CARD, 'account_id' => $this->cardCodeId])
                ->column('gift_id');
        }

        // 全部礼品
        $giftList = GiftMain::where(['status' => GiftMain::STATUS_NORMAL])
            ->where('find_in_set(:aid, `card_ids`)', ['aid' => $this->cardData->id])
            ->where('start_time', ['>', 0], ['<=', time()], 'and')
            ->where('end_time', ['>', 0], ['>', time()], 'and')
            ->order('weight DESC, id DESC')->select();
        $giftList = Super::arrayGetSet($giftList, [
            'id',
            'type',
            'name',
            'cover_url',
            'worth',
            'amount',
            'multi_spec',
            'count_left',
            'count_gain',
            'state' => function ($item) use ($giftIds) {
                return in_array($item->id, $giftIds) ? 2 : 1;
            },
            'created_at',
        ], true);

        $this->success('操作成功', compact('cardData', 'cardCodeData', 'giftList'));
    }

    // 获取礼品详情
    public function getDetail()
    {
        $giftId = $this->request->post('id');
        $gift = $this->validGift($giftId);

        $result = Super::arrayGetSet($gift, [
            'id',
            'type',
            'name',
            'cover_url',
            'photo_list',
            'content',
            'worth',
            'amount',
            'multi_spec',
            'count_left',
            'count_gain',
            'external_link',
            'created_at',
        ]);
        if ($gift->multi_spec) {
            if (! $giftSpecList = $gift->giftSpecListData) {
                $this->error('礼品数据无效，缺少规格');
            }
            $result['spec_list'] = Super::arrayGetSet($giftSpecList, [
                'id',
                'name',
                'worth',
                'amount',
                'count_left',
                'count_gain'
            ], true);
            $result['order_worth'] = $giftSpecList[0]->worth;
        } else {
            $result['spec_list'] = null;
            $result['order_worth'] = $gift->worth;
            $result['order_amount'] = $gift->amount;
        }
        $orderState = 0;
        if ($this->cardData->state == CardMain::STATE_READY) {
            $orderState = 1;
        } elseif ($this->cardData->state == CardMain::STATE_END) {
            $orderState = 2;
        } elseif ($this->cardCodeData->chance_use >= $this->cardData->chance_count) {
            $orderState = 3;
        } elseif ($gift->count_left <= 0) {
            $orderState = 4;
        } else {
            // 已兑礼品
            if ($this->cardData->gift_limit) {
                $giftIds = GiftOrder::where(['type' => GiftOrder::TYPE_CARD, 'account_id' => $this->cardCodeId])
                    ->column('gift_id');
                if (in_array($gift->id, $giftIds)) {
                    $orderState = 5;
                }
            }
            if (isset($result['spec_list']) && $result['spec_list'][0]['count_left'] <= 0) {
                $orderState = 4;
            }
        }
        $result['order_state'] = $orderState;

        $this->success('success', $result);
    }

    // 兑换预览
    public function getPreview()
    {
        $giftId = $this->request->post('gift_id');
        $specId = $this->request->post('gift_spec_id');
        $gift = $this->validGift($giftId);
        if ($this->cardData->state != CardMain::STATE_ING) {
            $this->error('兑换未开启或已结束');
        }

        $result['gift_data'] = Super::arrayGetSet($gift, [
            'id',
            'type',
            'name',
            'cover_url',
            'worth',
            'amount',
            'count_left',
            'count_gain',
            'gain_methods',
            'offline_place',
            'external_link'
        ]);
        if ($giftSpec = GiftSpec::get($specId)) {
            if ($giftSpec->gift_id != $giftId) {
                $this->error('规格不存在');
            }
            $result['gift_data']['spec_data'] = Super::arrayGetSet($giftSpec, ['id', 'name', 'worth', 'amount']);
            $result['gift_data']['order_worth'] = $giftSpec->worth;
            $result['gift_data']['order_amount'] = $giftSpec->amount;
        } else {
            $result['gift_data']['order_worth'] = $gift->worth;
            $result['gift_data']['order_amount'] = $gift->amount;
        }

        $result['chance_data'] = ['chance_left' => $this->cardData->chance_count - $this->cardCodeData->chance_use];

        $this->success('success', $result);
    }

    // 兑换礼品
    public function exchange()
    {
        // 参数校验
        $data = $this->request->post();
        $validate = new Validate([
            'gift_id' => 'require',
        ]);
        if (! $validate->check($data)) {
            $this->error($validate->getError());
        }
        $giftId = $data['gift_id'];
        $gift = $this->validGift($giftId);
        if ($this->cardData->state != CardMain::STATE_ING) {
            $this->error('兑换未开启或已结束');
        }

        // 校验领取方式
        $gainMethod = $data['gain_method'] ?? 0;
        if ($gift['type'] == GiftMain::TYPE_1) {
            if ($gainMethod == 0) {
                $this->error('领取方式未填写');
            }
            if ($gainMethod == GiftOrder::GAIN_METHOD_EXPRESS) {
                if (empty($data['address'])) {
                    $this->error('收货地址未填写');
                }
            } elseif ($gainMethod != GiftOrder::GAIN_METHOD_SELF) {
                $this->error('领取方式无效');
            }
        } else {
            $data['gain_method'] = GiftOrder::GAIN_METHOD_NONE;
        }

        // 校验商品库存
        if ($gift->count_left <= 0) {
            $this->error('库存不足');
        }

        // 商品信息
        $giftData = Super::arrayGetSet($gift, [
            'id',
            'name',
            'cover_url' => function ($item) {
                return $item->getData('cover_url');
            },
            'type',
            'type_text',
            'worth',
            'offline_place',
            'external_link'
        ]);

        // 校验规格库存
        $giftSpec = null;
        if ($giftSpecId = $data['gift_spec_id']) {
            if (! $gift->multi_spec) {
                $this->error('无需指定规格');
            }
            if (! $giftSpec = GiftSpec::get(['id' => $giftSpecId, 'gift_id' => $gift->id])) {
                $this->error('礼品规格不存在');
            }
            if ($giftSpec->count_left <= 0) {
                $this->error('库存不足');
            }
            $giftData['spec_data'] = Super::arrayGetSet($giftSpec, ['id', 'name', 'worth']);
            $giftData['order_worth'] = $giftSpec->worth;
        } else {
            if ($gift->multi_spec) {
                $this->error('还未选择规格');
            }
            $giftData['order_worth'] = $gift->worth;
        }

        // 兑换次数的限制
        $gainTimes = 1;
        if ($gift->limit_user || $this->cardData->gift_limit) {
            $gainTimes = GiftOrder::where([
                'gift_id'    => $gift->id,
                'type'       => GiftOrder::TYPE_CARD,
                'account_id' => $this->cardCodeId
            ])->count();
            if ($this->cardData->gift_limit) {
                if ($gainTimes > 0) {
                    $this->error('当前礼品已达到兑换次数的限制');
                }
            } else {
                if ($gainTimes >= $gift->limit_user) {
                    $this->error('当前礼品已达到兑换次数的限制');
                }
            }
        }

        // 增加订单
        $giftOrder = new GiftOrder();
        $giftOrder->data(Super::arrayGetSet($data, [
            'gain_method',
            'name',
            'phone',
            'province',
            'city',
            'area',
            'address',
            'note',
            'gift_id',
            'gift_spec_id',
        ]));
        $giftOrder['type'] = GiftOrder::TYPE_CARD;
        $giftOrder->model_id = $this->cardId;
        $giftOrder->account_id = $this->cardCodeId;


        // 发放券码
        $giftCode = null;
        if ($gift['type'] == GiftMain::TYPE_2) {
            $where = ['gift_id' => $gift->id, 'status' => GiftCode::STATUS_NORMAL];
            if ($giftSpec) {
                $where['gift_spec_id'] = $giftSpec->id;
            } else {
                $where['gift_spec_id'] = 0;
            }
            if (! $giftCode = GiftCode::where($where)->orderRaw('rand()')->find()) {
                $this->error('礼品已领取完');
            }
            // 标记已使用
            $giftCode->status = GiftCode::STATUS_GAINED;
            $giftOrder->gift_code_id = $giftCode->id;
            $giftOrder->status = GiftOrder::STATUS_HAS_DEPLOY;
            $giftOrder->deployed_at = time();
            $giftData['code_data'] = Super::arrayGetSet($giftCode, ['id', 'data']);
        } else {
            $giftOrder->status = GiftOrder::STATUS_WAIT_DEPLOY;
        }
        $giftOrder->gift_data = json_encode($giftData);
        $giftOrder->gift_type = $gift['type'];

        // 事务处理
        Db::startTrans();
        try {
            if (! $cardCode = CardCode::where(['id' => $this->cardCodeId])->lock(true)->find()) {
                $this->error(__('礼卡无效'));
            }
            if ($this->cardData->chance_count - $cardCode->chance_use <= 0) {
                $this->error(__('兑换机会已用完'));
            }

            // 增加使用次数
            $cardCode->chance_use++;
            if ($cardCode->status == CardCode::STATUS_HAS_VALID) {
                $cardCode->status = CardCode::STATUS_HAS_EXCHANGE;
            }
            $cardCode->save();

            // 防重校验
            if ($gift->limit_user) {
                Norepeat::tryAddData('gift:gain_times',
                    $gift->id . ':' . $giftOrder['type'] . ':' . $giftOrder->account_id . ':' . $gainTimes . ':' . date('ymdHi'));
            }

            // 更新商品库存
            Logic::niceAssert(GiftMain::where(['id' => $gift->id])->where('count_left', '>', 0)
                ->update(['count_left' => Db::raw('count_left-1'), 'count_gain' => Db::raw('count_gain+1')]),
                '库存不足');

            // 更新规格库存
            if ($giftSpec) {
                Logic::niceAssert(GiftSpec::where(['id' => $giftSpec->id])->where('count_left', '>', 0)
                    ->update(['count_left' => Db::raw('count_left-1'), 'count_gain' => Db::raw('count_gain+1')]),
                    '库存不足');
            }

            // 标记code
            if ($giftCode) {
                Logic::niceAssert(GiftCode::where(['id' => $giftCode->id])->where(['status' => GiftCode::STATUS_NORMAL])
                    ->update(['status' => GiftCode::STATUS_GAINED]), '领取失败，请稍后再试');
            }

            // 增加订单
            $giftOrder->save();
            $giftOrder->number = 'NYX' . date('ymd') . str_pad($giftOrder->id, 8, '0', STR_PAD_LEFT);  // 订单编号
            $giftOrder->save();

            Db::commit();
        } catch (PDOException | Exception $e) {
            Db::rollback();
            $this->error($e->getMessage());
        }
        Logic::sendExchangeMessage($giftOrder->id);  // 发送兑换消息

        $this->success('success', ['id' => $giftOrder->id]);
    }

    // 获取兑换列表
    public function getOrderList()
    {
        $group = $this->request->post('group');

        // 数据列表
        $query = GiftOrder::where(['type' => GiftOrder::TYPE_CARD, 'account_id' => $this->cardCodeId])
            ->order('id DESC');
        if ($group) {
            $query->where(['status' => $group]);
        }
        $result = $query->paginate($this->request->post('page_size', 10), false);
        $result = Logic::getPageData($result, [
            'id',
            'number',
            'gift_data'   => 'giftDataArray',
            'gain_method',
            'status',
            'status_text' => 'statusText',
            'created_at',
        ]);

        $this->success('success', $result);
    }


    // 获取兑换详情
    public function getOrderDetail()
    {
        $orderId = $this->request->post('id');
        if (! $giftOrder = GiftOrder::get([
            'id'         => $orderId,
            'account_id' => $this->cardCodeId,
        ])) {
            $this->error('订单不存在');
        }

        $result = Super::arrayGetSet($giftOrder, [
            'id',
            'number',
            'gift_data'    => 'giftDataArray',
            'gain_method',
            'name',
            'phone',
            'address_data' => function ($item) {
                if ($item->gain_method != GiftOrder::GAIN_METHOD_EXPRESS) {
                    return null;
                }
                $giftData = $item->giftDataArray;
                if ($giftData['type'] != GiftMain::TYPE_1) {
                    return null;
                }

                return Super::arrayGetSet($item, ['name', 'phone', 'province', 'city', 'area', 'address']);
            },
            'express_data' => function ($item) {
                if ($item->gain_method != GiftOrder::GAIN_METHOD_EXPRESS) {
                    return null;
                }
                $giftData = $item->giftDataArray;
                if ($giftData['type'] != GiftMain::TYPE_1) {
                    return null;
                }
                if ($item->status != GiftOrder::STATUS_HAS_DEPLOY) {
                    return null;
                }

                return [
                    'company'     => $item->express_company_text,
                    'number'      => $item->express_number,
                    'deployed_at' => $item->deployed_at
                ];
            },
            'note',
            'status',
            'status_text'  => 'statusText',
            'deployed_at',
            'created_at',
            'express_note',
        ]);

        $this->success('success', $result);
    }

    // 获取物流动态
    public function getExpressFeed()
    {
        $giftId = $this->request->post('id');
        if (! $giftOrder = GiftOrder::get([
            'id'         => $giftId,
            'account_id' => $this->cardCodeId,
        ])) {
            $this->error('订单不存在');
        }

        try {
            $result = Logic::queryExpressTrack($giftOrder->express_company, $giftOrder->express_number,
                $giftOrder->express_phone);
        } catch (Exception $e) {
            $this->error($e->getMessage());
        }
        $result['address'] = $giftOrder['province'] . $giftOrder['city'] . $giftOrder['area'] . $giftOrder['address'];
        $result['deployed_at'] = $giftOrder->deployed_at;
        $result['company'] = $giftOrder->expressCompanyText;

        $this->success('success', $result);
    }

    // 订单取消
    public function orderCancel()
    {
        $orderId = $this->request->post('order_id');

        Db::startTrans();
        try {
            // 订单数据
            $giftOrder = GiftOrder::where([
                'id'         => $orderId,
                'account_id' => $this->cardCodeId,
            ])->lock(true)->find();
            if (! $giftOrder) {
                $this->error('订单不存在');
            }
            if ($giftOrder->status != GiftOrder::STATUS_WAIT_DEPLOY) {
                $this->error('只支持取消待发货订单');
            }

            // 商品类型
            $giftData = $giftOrder->giftDataArray;
            if ($giftData['type'] != GiftMain::TYPE_1) {
                $this->error('只支持取消兑换实物订单');
            }

            // 更新订单状态
            $giftOrder->status = GiftOrder::STATUS_HAS_BACK;
            $giftOrder->save();

            // 退回礼品库存
            $gift = GiftMain::get($giftOrder->gift_id);
            if (! $gift || $gift['type'] != $giftData['type'] || ($gift->multi_spec && ! $giftOrder->gift_spec_id)) {
                throw new Exception($giftData['name'] . '礼品变更过，不能进行取消退回');
            }
            GiftMain::where(['id' => $gift->id])->inc('count_left')->dec('count_gain')->update();

            // 退回礼品规格规格
            if ($giftOrder->gift_spec_id) {
                if (! $giftSpec = GiftSpec::get($giftOrder->gift_spec_id)) {
                    throw new Exception($giftData['spec_data']['name'] . '规格被删除，不能进行取消退回');
                }
                GiftSpec::where(['id' => $giftSpec->id])->inc('count_left')->dec('count_gain')->update();
            }

            // 退回机会
            Logic::niceAssert(CardCode::where(['id' => $giftOrder->account_id])
                ->update(['chance_use' => Db::raw('chance_use-1')]), '取消退回失败，请稍后再试');
            Db::commit();
        } catch (PDOException | Exception $e) {
            Db::rollback();
            $this->error($e->getMessage());
        }

        $this->success('success', []);
    }

    /**
     * 校验礼品
     *
     * @param $giftId
     * @return GiftMain
     */
    private function validGift($giftId)
    {
        if (! $gift = GiftMain::get($giftId)) {
            $this->error('礼品无效');
        }
        if ($gift->status != GiftMain::STATUS_NORMAL) {
            $this->error('礼品已下架');
        }
        if (($gift->start_time && $gift->start_time > time()) || ($gift->end_time && $gift->end_time <= time())) {
            $this->error('礼品已下架');
        }
        $activityIds = $gift->card_ids ? explode(',', $gift->card_ids) : [];
        if (! in_array($this->cardId, $activityIds)) {
            $this->error('没有兑换权限');
        }

        return $gift;
    }
}
